/*
 * @brief:
 * @Author: TzzzT
 * @Date: 2022-05-10 13:59:19
 * @LastEditTime: 2023-05-04 01:22:21
 * @LastEditors: TzzzT
 */

#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_gap_ble_api.h"
#include "esp_gatt_defs.h"
#include "esp_mac.h"

#include "string.h"

#include "myble.h"
#include "RCS_master.h"
#include "RCS_ble_master.h"
#include "RCS_net.h"
#include "bc260.h"
#include "cJSON.h"
#include "RCS_protocol.h"
#include "find_string.h"
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
static const char *BLE_TAG = "BLE_TAG";
extern rcs_mast_system_t rcsSystem;
extern QueueHandle_t xGameQueue;
static SemaphoreHandle_t openMutex = NULL;
static SemaphoreHandle_t scanMutex = NULL;

static char adv_name_table[ADV_CLASS_NUM][12] = {
    "SAFETY",
    "TEAM_A",
    "TEAM_B",
    "REBORN",
    "HP_DROP",
    "HP_CURE",
    "INVINCIBLE"};

bool allow_open_server = true;
bool allow_scan_new_slave = false;
// 扫描结果转换
station_item_t station_array[ADV_CLASS_NUM] = {0};

station_list_t station_list[DYNAMIC_STATION_NUM];

esp_err_t
store_bda_to_nvs(uint8_t equip_sn);

void set_allow_open(bool st)
{
  xSemaphoreTake(openMutex, portMAX_DELAY);
  allow_open_server = st;
  xSemaphoreGive(openMutex);
}

bool is_allow_open_ble_server(void)
{
  return allow_open_server;
}

void set_allow_scan_new_slave_flag(bool st)
{
  xSemaphoreTake(scanMutex, portMAX_DELAY);
  allow_scan_new_slave = st;
  // ESP_LOGI("scan", "set allow_scan_new_slave:%d", allow_scan_new_slave);
  xSemaphoreGive(scanMutex);
}

static void open_evt_cb(uint8_t equip_sn, esp_bd_addr_t bda, bool status)
{
  // ESP_LOGI("open", "equip_sn:%d, result:%d", equip_sn, status);
  if (status)
  {
    switch (equip_sn)
    {
    case PROFILE_GUNPOINT_ID:
      ESP_LOGE(BLE_TAG, "GUN POINT CONNECT!");
      rcsSystem.equip.pri_weapon.point.is_hold = true;
      memcpy(rcsSystem.equip.pri_weapon.point.ser_bda, bda, 6);
      store_bda_to_nvs(GUN_POINT_CLASS);
      break;
    case PROFILE_GUNSCREEN_ID:
      ESP_LOGE(BLE_TAG, "GUN SCREEN CONNECT!");
      rcsSystem.equip.pri_weapon.screen.is_hold = true;
      memcpy(rcsSystem.equip.pri_weapon.screen.ser_bda, bda, 6);
      store_bda_to_nvs(GUN_SCREEN_CLASS);
      break;
    case PROFILE_ARMOR_ID:
      ESP_LOGE(BLE_TAG, "ARMOR CONNECT!");
      rcsSystem.equip.armor.is_hold = true;
      memcpy(rcsSystem.equip.armor.ser_bda, bda, 6);
      store_bda_to_nvs(ARMOR_CLASS);
      break;
    default:
      break;
    }
    rcsSystem.equip.conn_num += 1;
    // 连接一次以后自动关闭
    set_allow_scan_new_slave_flag(false);
  }
  set_allow_open(true);
  return;
}
static void notify_from_server_cb(uint8_t equip_sn, esp_bd_addr_t remote_bda, uint8_t *buf, size_t len)
{
  ESP_LOGI(BLE_TAG, "notify_from_server_cb");
  // 先判断一次包长度是否和数据内容里的包长度一致，如果不一致说明是未知消息，上报给服务器。
  if (len < 3 || buf[1] != PACKAGE_LEN_UPL || buf[2] != len)
  {
    ESP_LOGE(BLE_TAG, "package invalid from equip:%d", equip_sn);
    return;
  }
  // 蓝牙线程里不解析数据内容，直接发给game thread处理
  ESP_LOGI(BLE_TAG,"get ble server packagee");
  if (xQueueSend(xGameQueue, buf, pdMS_TO_TICKS(200)) != pdPASS)
  {
    ESP_LOGE(BLE_TAG, "queue full.");
  }
}

static void disconnect_evt_cb(uint8_t equip_sn, esp_bd_addr_t remote_bda, uint8_t rsn)
{
  ESP_LOGE(BLE_TAG, "disconnect_evt_cb, reason:%d", rsn);
  if (rsn == ESP_GATT_CONN_TERMINATE_LOCAL_HOST)
  {
    ESP_LOGE(BLE_TAG, "rsn: by self.");
  }
  else
  {
    ESP_LOGE(BLE_TAG, "slave disconnect accidentally.");
  }

  // 不知道为什么，有时莫名其妙触发这个事件
  if (rcsSystem.equip.conn_num > 0)
  {
    rcsSystem.equip.conn_num--;
    switch (equip_sn)
    {
    case PROFILE_GUNPOINT_ID:
      rcsSystem.equip.pri_weapon.point.is_hold = false;
      rcsSystem.equip.pri_weapon.point.batt = -1;
      break;
    case PROFILE_GUNSCREEN_ID:
      rcsSystem.equip.pri_weapon.screen.is_hold = false;
      rcsSystem.equip.pri_weapon.screen.batt = -1;
      break;
    case PROFILE_ARMOR_ID:
      rcsSystem.equip.armor.is_hold = false;
      rcsSystem.equip.armor.batt = -1;
      break;
    default:
      ESP_LOGE(BLE_TAG, "unknown device, id:%d.", equip_sn);
      break;
    }
    // 更新屏幕数字
    if (rcsSystem.equip.pri_weapon.screen.is_hold)
    {
      // ESP_LOGE(BLE_TAG,"screen.is_hold, update connet device num");
      uint16_t packlen;
      notify_mask_t mask = (1 << CONN_CLI_NUM_NOTIFY) | (1 << SCRBATT_NOTIFY);
      uint8_t *package = make_sync_data_package(&packlen, mask);
      rcs_send_to_bleserver(GUN_SCREEN_CLASS, package, packlen);
      free(package);
    }
    else
    {
    }
  }
  else
  {
    ESP_LOGE(BLE_TAG, "no slave, but disconnect sth.");
  }
}

void handle_dynamic_sta_list(dynamic_sta_type_t idx, uint32_t id, int8_t rssi);
int16_t set_station_rssi(int16_t old_value, int8_t rssi);

static void scan_result_cb(esp_bd_addr_t bda, uint8_t *adv_name, uint8_t name_len, int8_t rssi, uint8_t *if_connect)
{
  uint8_t i;
  uint32_t station_id = 0;
  char id_ch[7] = {0};
  char default_ch[4] = "DEF";
  char resource_ch[4] = "RES";
  *if_connect = 0;
  if (name_len == 9 && memcmp(adv_name, default_ch, 3) == 0)
  {
    memcpy(id_ch, adv_name + 3, 6);
    station_id = atoi(id_ch);
    // ESP_LOGE("SCAN", "default id : %d", station_id);
    handle_dynamic_sta_list(DEFAULT_STATION, station_id, rssi);
    goto end_lable;
  }
  else if (name_len == 9 && memcmp(adv_name, resource_ch, 3) == 0)
  {
    memcpy(id_ch, adv_name + 3, 6);
    station_id = atoi(id_ch);
    // ESP_LOGE("SCAN", "resource id : %d", station_id);
    handle_dynamic_sta_list(RESOURCE_STATION, station_id, rssi);
    goto end_lable;
  }

  // 检测除了资源点和默认点
  for (i = 0; i < ADV_CLASS_NUM; ++i)
  {
    if (name_len < 12)
    {
      if (memcmp(adv_name, adv_name_table[i], name_len) == 0)
      {
        if (station_array[i].count == 0)
        {
          station_array[i].st = RISE;
        }
        station_array[i].count = 4;
        station_array[i].avg_rssi = set_station_rssi(station_array[i].avg_rssi, rssi);
        goto end_lable;
      }
    }
    else
    {
      // ESP_LOGE(BLE_TAG,"scan unknown device");
    }
  }
  // 检测从机
  if (memcmp(adv_name, "GUN-POI-N", 9) == 0)
  {
    if (memcmp(bda, rcsSystem.equip.pri_weapon.point.ser_bda, 6) == 0 &&
        !rcsSystem.equip.pri_weapon.point.is_hold)
    {
      ESP_LOGE("SCAN", "get lost GUN-POI-N device");
      set_remote_bda(GUN_POINT_CLASS, rcsSystem.equip.pri_weapon.point.ser_bda);
      rcs_try_to_open_server(GUN_POINT_CLASS);
      *if_connect = 1;
      goto end_lable;
    }
  }
  if (memcmp(adv_name, "GUN-SCR-N", 9) == 0)
  {
    if (memcmp(bda, rcsSystem.equip.pri_weapon.screen.ser_bda, 6) == 0 &&
        !rcsSystem.equip.pri_weapon.screen.is_hold)
    {
      ESP_LOGE("SCAN", "get lost GUN-SCR-N device");
      set_remote_bda(GUN_SCREEN_CLASS, rcsSystem.equip.pri_weapon.screen.ser_bda);
      rcs_try_to_open_server(GUN_SCREEN_CLASS);
      *if_connect = 1;
      goto end_lable;
    }
  }
  if (memcmp(adv_name, "ARMOR-N", 7) == 0)
  {
    if (memcmp(bda, rcsSystem.equip.armor.ser_bda, 6) == 0 &&
        !rcsSystem.equip.armor.is_hold)
    {
      ESP_LOGE("SCAN", "get lost ARMOR-N device");
      set_remote_bda(ARMOR_CLASS, rcsSystem.equip.armor.ser_bda);
      rcs_try_to_open_server(ARMOR_CLASS);
      *if_connect = 1;
      goto end_lable;
    }
  }

  if (memcmp(adv_name, "GUN-POI-Y", 9) == 0)
  {
    esp_log_buffer_hex("GUN-POI-Y BDA", bda, 6);
    ESP_LOGE("SCAN", "allow_scan_new_slave:%d", allow_scan_new_slave);
    if (allow_scan_new_slave)
    {
      rcs_close_all_connection(GUN_POINT_CLASS);
      set_remote_bda(GUN_POINT_CLASS, bda);
      rcs_try_to_open_server(GUN_POINT_CLASS);
      *if_connect = 1;
    }
    goto end_lable;
  }
  if (memcmp(adv_name, "GUN-SCR-Y", 9) == 0)
  {
    esp_log_buffer_hex("GUN-SCR-Y BDA", bda, 6);
    ESP_LOGE("SCAN", "allow_scan_new_slave:%d", allow_scan_new_slave);
    if (allow_scan_new_slave)
    {
      rcs_close_all_connection(GUN_SCREEN_CLASS);
      set_remote_bda(GUN_SCREEN_CLASS, bda);
      rcs_try_to_open_server(GUN_SCREEN_CLASS);
      *if_connect = 1;
    }
    goto end_lable;
  }
  if (memcmp(adv_name, "ARMOR-Y", 7) == 0)
  {
    esp_log_buffer_hex("ARMOR-Y BDA", bda, 6);
    ESP_LOGE("SCAN", "allow_scan_new_slave:%d", allow_scan_new_slave);
    if (allow_scan_new_slave)
    {
      rcs_close_all_connection(ARMOR_CLASS);
      set_remote_bda(ARMOR_CLASS, bda);
      rcs_try_to_open_server(ARMOR_CLASS);
      *if_connect = 1;
    }
    goto end_lable;
  }

end_lable:
  return;
}

static void ble_mutex_create(void)
{
  /* 创建互斥信号量 */
  openMutex = xSemaphoreCreateMutex();
  if (openMutex == NULL)
  {
    ESP_LOGI(BLE_TAG, "openMutex Create failed");
  }

  scanMutex = xSemaphoreCreateMutex();
  if (scanMutex == NULL)
  {
    ESP_LOGI(BLE_TAG, "scanMutex Create failed");
  }
}

static void client_cb_register(void)
{
  client_func_t *fun;
  fun = get_client_func_p();
  fun->open_cb = open_evt_cb;
  fun->notify_cb = notify_from_server_cb;
  fun->disconn_cb = disconnect_evt_cb;
  fun->scan_result_cb = scan_result_cb;
  ble_mutex_create();
}

void rcs_set_remote_bda(uint8_t equip_sn, bd_addr_t remote_bda)
{
  set_remote_bda(equip_sn, remote_bda);
}

/*
有新的蓝牙地址时，先把蓝牙储存到驱动层，然后连接，连接上了以后再储存到结构体中，结构体和nvs的保持一致
*/

bool rcs_try_to_open_server(uint8_t equip_sn)
{
  bool res = false;
  if (allow_open_server)
  {
    set_allow_open(false);
    // ESP_LOGI(BLE_TAG, "allow open, start_connect");
    res = true;
    start_connect(equip_sn);
  }
  else
  {
    ESP_LOGE(BLE_TAG, "not allow");
  }
  return res;
}

void rcs_close_all_connection(uint8_t equip_sn)
{
  if (is_physical_connected(equip_sn))
  {
    close_physical_connection(equip_sn);
  }
}

void rcs_try_to_scanning(uint32_t scan_time)
{
  // ESP_LOGE(BLE_TAG, "set_scan_param");
  ble_client_set_scan_param(scan_time);
}

void rcs_stop_scan_server(void)
{
  stop_scan();
}

esp_err_t rcs_send_to_bleserver(uint8_t equip_sn, uint8_t *package, uint16_t package_len)
{
  ESP_LOGE(BLE_TAG, "send to server:%d", equip_sn);
  esp_err_t ret = ESP_FAIL;
  if (package == NULL || package_len == 0)
  {
    return ret;
  }
  // uint8_t retry_cnt = 10;
  // esp_log_buffer_char(BLE_TAG, package, package_len);
  // while (retry_cnt)
  // {
  //     retry_cnt--;

  //     if (ret == ESP_OK)
  //     {
  //         break;
  //     }
  //     else
  //     {
  //         ESP_LOGE(BLE_TAG, "send to server failed, retry");
  //     }
  //     vTaskDelay(pdMS_TO_TICKS(100));
  // }
  ret = write_char(equip_sn, package, package_len);
  return ret;
}

void ble_mast_init(void)
{
  client_cb_register();
  ble_client_init();
  init_station_list();
  // 读取上次的服务器到结构体
  ble_remember_last_server();
}

esp_err_t get_bda_from_nvs(uint8_t equip_sn);

#define RETRY_OPEN_SERVER 1
void ble_remember_last_server(void)
{
  esp_err_t err;
  err = get_bda_from_nvs(GUN_POINT_CLASS);
  if (err != ESP_OK)
  {
    ESP_LOGI(BLE_TAG, "no gun point");
  }
  else
  {
    ESP_LOGI(BLE_TAG, "last has gun point");
  }

  err = get_bda_from_nvs(GUN_SCREEN_CLASS);
  if (err != ESP_OK)
  {
    ESP_LOGI(BLE_TAG, "no gun screen");
  }
  else
  {
    ESP_LOGI(BLE_TAG, "last has gun screen");
  }

  err = get_bda_from_nvs(ARMOR_CLASS);
  if (err != ESP_OK)
  {
    ESP_LOGI(BLE_TAG, "no armor");
  }
  else
  {
    ESP_LOGI(BLE_TAG, "last has armor");
  }
}

// nvs

#define ARMOR_BDA_KEY "armor_bda_key"
#define POINT_BDA_KEY "point_bda_key"
#define SCREEN_BDA_KEY "screen_bda_key"

char bda_key[3][20] = {
    POINT_BDA_KEY,
    SCREEN_BDA_KEY,
    ARMOR_BDA_KEY};

esp_err_t store_bda_to_nvs(uint8_t equip_sn)
{
  nvs_handle bleNvsHandle;
  size_t len = BLUETOOTH_DEVICE_ADDR_LEN;
  esp_err_t err;

  err = nvs_open("ble_config", NVS_READWRITE, &bleNvsHandle);
  if (err != ESP_OK)
  {
    printf("Error (%s) opening NVS bleNvsHandle!\n", esp_err_to_name(err));
    return err;
  }
  switch (equip_sn)
  {
  case GUN_POINT_CLASS:
  {
    esp_log_buffer_hex(BLE_TAG, rcsSystem.equip.pri_weapon.point.ser_bda, sizeof(bd_addr_t));
    err = nvs_set_blob(bleNvsHandle, bda_key[GUN_POINT_CLASS], rcsSystem.equip.pri_weapon.point.ser_bda, len);
    break;
  }
  case GUN_SCREEN_CLASS:
  {
    esp_log_buffer_hex(BLE_TAG, rcsSystem.equip.pri_weapon.screen.ser_bda, sizeof(bd_addr_t));
    err = nvs_set_blob(bleNvsHandle, bda_key[GUN_SCREEN_CLASS], rcsSystem.equip.pri_weapon.screen.ser_bda, len);
    break;
  }
  case ARMOR_CLASS:
  {
    esp_log_buffer_hex(BLE_TAG, rcsSystem.equip.armor.ser_bda, sizeof(bd_addr_t));
    err = nvs_set_blob(bleNvsHandle, bda_key[ARMOR_CLASS], rcsSystem.equip.armor.ser_bda, len);
    break;
  }
  default:
    break;
  }
  if (err != ESP_OK)
  {
    printf("store_remote_bda_to_nvs failed, err(%s)\n", esp_err_to_name(err));
    return err;
  }
  else
  {
    // ESP_LOGI(SYS_TAG, "store_remote_bda_to_nvs successfully");
  }
  err = nvs_commit(bleNvsHandle);
  nvs_close(bleNvsHandle);
  return err;
}

esp_err_t get_bda_from_nvs(uint8_t equip_sn)
{
  nvs_handle bleNvsHandle;

  esp_err_t err;

  err = nvs_open("ble_config", NVS_READWRITE, &bleNvsHandle);
  if (err != ESP_OK)
  {
    printf("Error (%s) opening NVS bleNvsHandle!\n", esp_err_to_name(err));
    return err;
  }

  size_t len = BLUETOOTH_DEVICE_ADDR_LEN;
  uint8_t dummy_bda[6] = {0};
  err = nvs_get_blob(bleNvsHandle, &bda_key[equip_sn], dummy_bda, &len);

  if (err != ESP_OK)
  {
    printf("get_bda_from_nvs failed, err(%s)\n", esp_err_to_name(err));
    return err;
  }
  uint8_t zero_bda[6] = {0};
  if (memcmp(zero_bda, dummy_bda, 6) == 0)
  {
    ESP_LOGI(BLE_TAG, "bda is zero");
    err = ESP_ERR_NOT_FOUND;
    return err;
  }
  ESP_LOGI(BLE_TAG, "get bda");
  switch (equip_sn)
  {
  case GUN_POINT_CLASS:
  {
    memcpy(rcsSystem.equip.pri_weapon.point.ser_bda, dummy_bda, 6);
    break;
  }
  case GUN_SCREEN_CLASS:
  {
    memcpy(rcsSystem.equip.pri_weapon.screen.ser_bda, dummy_bda, 6);
    break;
  }
  case ARMOR_CLASS:
  {
    memcpy(rcsSystem.equip.armor.ser_bda, dummy_bda, 6);
    break;
  }
  default:
    break;
  }

  err = nvs_commit(bleNvsHandle);
  nvs_close(bleNvsHandle);
  return err;
}

/************STATION SCAN HANDLE***************/
/**
 * scan cb函数中：得到一个基站的rssi和id。
 *
 *
 * update 线程中，更新基站的存活状况。如果超过1s以后没再次检测到认为关闭。
 *
 *
 *
 */
void init_station_list(void)
{
  for (size_t i = 0; i < ADV_CLASS_NUM; i++)
  {
    station_array[i].avg_rssi = 0;
    station_array[i].count = 0;
    station_array[i].st = KEEP_NO;
  }

  station_list[DEFAULT_STATION].fake_head = calloc(1, sizeof(station_node_t));
  station_list[DEFAULT_STATION].fake_head->next_node = NULL;

  station_list[RESOURCE_STATION].fake_head = calloc(1, sizeof(station_node_t));
  station_list[RESOURCE_STATION].fake_head->next_node = NULL;
  return;
}

void handle_dynamic_sta_list(dynamic_sta_type_t idx, uint32_t id, int8_t rssi)
{
  bool finish = false;
  station_node_t *temp = station_list[idx].fake_head->next_node;
  station_node_t *last = station_list[idx].fake_head;
  while (temp != NULL)
  {
    if (temp->id == id)
    {
      // ESP_LOGE(BLE_TAG, "old [%d] station: %d", idx, id);
      temp->count = 4;
      temp->avg_rssi = set_station_rssi(temp->avg_rssi, rssi);
      finish = true;
      break;
    }
    last = temp;
    temp = temp->next_node;
  }
  if (!finish)
  {
    ESP_LOGE(BLE_TAG, "add new [%d] station: %" PRIu32 "", idx, id);

    temp = calloc(1, sizeof(station_node_t));
    temp->avg_rssi = rssi;
    temp->id = id;
    temp->count = 4;
    temp->next_node = NULL;
    last->next_node = temp;
  }
}

void update_dynamic_sta_list(dynamic_sta_type_t idx)
{
  station_node_t *pre = station_list[idx].fake_head;
  station_node_t *temp;
  while (pre->next_node != NULL)
  {
    temp = pre->next_node;
    temp->count--;
    if (temp->count == 0)
    {
      // 如果temp是需要删除的，pre不变，pre的下一个指向temp的下一个
      pre->next_node = temp->next_node;
      ESP_LOGE(BLE_TAG, "delete [%d] station: %" PRIu32 "", idx, temp->id);
      free(temp);
      // ESP_LOGI(BLE_TAG, "Free memory: %d bytes", esp_get_free_heap_size());
    }
    else
    {
      pre = pre->next_node;
    }
  }
}

// station_invincible_handle(true);

// 每种基站的计数减1.结果返回是否计数变成0(代表离开了某种基站)
void update_uni_station(void)
{
  for (int i = SAFETY_STATION; i < ADV_CLASS_NUM; ++i)
  {
    if (station_array[i].count == 0)
    {
      station_array[i].st = KEEP_NO;
    }
    else
    {
      if (station_array[i].count > 1)
      {

        station_array[i].st = KEEP_HOLD;
      }
      else if (station_array[i].count == 1)
      {
        station_array[i].st = DOWN;
      }
      station_array[i].count--;
    }
  }
}

int16_t set_station_rssi(int16_t old_value, int8_t rssi)
{
  int16_t rssi_all;
  if (old_value == 0)
  {
    rssi_all = rssi;
  }
  else
  {
    rssi_all = old_value * 4 + rssi;
    rssi_all /= 5;
  }
  return rssi_all;
  // ESP_LOGI("rssi", "new rssi: %d, avg rssi: %d", rssi, station_array[adv_type].avg_rssi);
}

void select_team(void)
{
  // jiasuo
  uint8_t command = 0;
  bool team_a = false;
  bool team_b = false;
  if (station_array[TEAM_A_STATION].count != 0)
  {
    command = TEAM_A_STA_COMM;
    team_a = true;
  }
  if (station_array[TEAM_B_STATION].count != 0)
  {
    command = TEAM_B_STA_COMM;
    team_b = true;
  }
  if (team_a && team_b)
  {
    if (station_array[TEAM_A_STATION].avg_rssi >
        station_array[TEAM_B_STATION].avg_rssi)
    {
      command = TEAM_A_STA_COMM;
    }
    else
    {
      command = TEAM_B_STA_COMM;
    }
    // ESP_LOGI(BLE_TAG, "sta A: %d, sta B: %d",
    //     station_array[TEAM_A_STATION].avg_rssi,
    //     station_array[TEAM_B_STATION].avg_rssi);
  }
  if (command != 0)
  {
    uint8_t *package = make_prop_command_package(command, rcsSystem.equip.core.battery);
    if (xQueueSend(xGameQueue, package, pdMS_TO_TICKS(200)) != pdPASS)
    {
      ESP_LOGI(BLE_TAG, "queue full.");
    }
    free(package);
  }
  // suo
  return;
}

void station_hp_handle(void)
{
  uint8_t command = 0;
  bool cure_hp = false;
  bool drop_hp = false;
  if (station_array[HP_CURE_STATION].count != 0)
  {
    command = HP_CURE_STA_COMM;
    cure_hp = true;
  }
  if (station_array[HP_DROP_STATION].count != 0)
  {
    command = HP_DROP_STA_COMM;
    drop_hp = true;
  }
  if (cure_hp && drop_hp)
  {
    if (station_array[HP_CURE_STATION].avg_rssi >
        station_array[HP_DROP_STATION].avg_rssi)
    {
      command = HP_CURE_STA_COMM;
    }
    else
    {
      command = HP_DROP_STA_COMM;
    }
    // ESP_LOGI(BLE_TAG, "HP cure: %d, drop: %d, command: %d",
    //     station_array[HP_CURE_STA_COMM].avg_rssi,
    //     station_array[HP_DROP_STA_COMM].avg_rssi, command);
  }
  if (command != 0)
  {
    uint8_t *package = make_prop_command_package(command, rcsSystem.equip.core.battery);
    // set_game_event(REMOTE_COMM_EVENT, 4);
    // ESP_LOGI("station_hp_handle","receive command: %d", command);
    if (xQueueSend(xGameQueue, package, pdMS_TO_TICKS(200)) != pdPASS)
    {
      ESP_LOGI(BLE_TAG, "queue full.");
    }
    free(package);
  }
  return;
}

void station_reborn_handle(void)
{
  if (station_array[REBORN_STATION].count != 0)
  {
    if (!rcsSystem.game.player.living)
    {
      uint8_t *package = make_prop_command_package(REBORN_P_STA_COMM, rcsSystem.equip.core.battery);
      // set_game_event(REMOTE_COMM_EVENT, 8);
      // ESP_LOGI("station_reborn_handle","REBORN_P_STA_COMM");
      if (xQueueSend(xGameQueue, package, pdMS_TO_TICKS(200)) != pdPASS)
      {
        ESP_LOGI(BLE_TAG, "queue full.");
      }
      free(package);
    }
  }
  return;
}

void period_dynamic_station_handle(dynamic_sta_type_t idx)
{
  station_node_t *temp = station_list[idx].fake_head->next_node;
  uint32_t param_arr[2] = {0};
  size_t message_length;
  while (temp != NULL)
  {
    param_arr[0] = STATION_UNKNOWN;
    param_arr[1] = temp->id;
    // ESP_LOGI(BLE_TAG, "has default sta");
    char *message = make_net_json_package(ERROR_NET_UP, &message_length, param_arr);
    if (message)
    {
      bc_send_package_to_server(message, message_length);
      free(message);
    }
    temp = temp->next_node;
  }
  return;
}

void report_default_station(void)
{
  station_node_t *temp = station_list[DEFAULT_STATION].fake_head->next_node;
  uint32_t param_arr[2] = {0};
  size_t message_length;
  while (temp != NULL)
  {
    param_arr[0] = STATION_UNKNOWN;
    param_arr[1] = temp->id;

    char *message = make_net_json_package(ERROR_NET_UP, &message_length, param_arr);
    if (message)
    {
      bc_send_package_to_server(message, message_length);
      free(message);
    }
    temp = temp->next_node;
  }
  return;
}

void station_invincible_handle(void)
{
  if (station_array[INVINCIBLE_STATION].st == DOWN)
  {
    uint8_t *package = make_prop_command_package(INVINCIBLE_STA_COMM, rcsSystem.equip.core.battery);
    if (xQueueSend(xGameQueue, package, pdMS_TO_TICKS(200)) != pdPASS)
    {
      ESP_LOGI(BLE_TAG, "queue full.");
    }
    free(package);
  }
  return;
}
